﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Threading;

namespace CasinoApp.Tools
{
    /// <summary>
    /// Timer für die Lauf-Zeit der SlotMachine und rechtzeitige Stoppen der einzelnen Slots.
    /// </summary>
    /// <param author="">Aeschlimann Thomas, 2011 AXA</param>
    public class SlotMachineTimer
    {
        #region Fields

        /// <summary>
        /// Speichert die Anzahl der Slots für der SlotMachine.
        /// </summary>
        private int _numberOfSlots;

        /// <summary>
        /// Speichert die Anzahl Sekunden die während die SlotMachine laufen soll.
        /// </summary>
        private int _runDurationSeconds;

        /// <summary>
        /// Speichert den Wert für das Aufzählen der vergangenen Sekunden während die SlotMachine läuft.
        /// </summary>
        private int _runSecondsCount;

        /// <summary>
        /// Speichert den Status ob der Run-Timer gestoppt ist.
        /// </summary>
        private volatile bool _stopRunningSequence;

        /// <summary>
        /// Speichert den Sekunden-Abstand, in welchem die einzelnen Slots gestoppt werden sollen.
        /// </summary>
        private int _stopIntervalSeconds;

        /// <summary>
        /// Speichert den Wert für das Aufzählen der vergangenen Sekunden zwischen dem Stoppen der einzelnen Slots.
        /// </summary>
        private int _stopSecondsCount;

        /// <summary>
        /// Speichert die Anzahl bereits gestoppter Slots der SlotMachine.
        /// </summary>
        private int _stoppedSlotsCount;

        /// <summary>
        /// Speichert den Status ob der Stop-Timer gestoppt ist.
        /// </summary>
        private volatile bool _stopStoppingSequence;

        #endregion // Fields

        #region // Konstruktoren

        /// <summary>
        /// Konstruktor unter Angabe der Anzahl Slots der SlotMachine.
        /// </summary>
        public SlotMachineTimer(int numberOfSlots)
        {
            _numberOfSlots = numberOfSlots;
        }

        #endregion // Konstruktoren

        #region Events

        /// <summary>
        /// Event der gefeuert wird, wenn ein Slot gestoppt werden soll.
        /// </summary>
        public event EventHandler<StopSlotRequestedEventArgs> StopSlotRequested;

        /// <summary>
        /// Event der gefeuert wird, wenn der Stop-Timer gestoppt wurde.
        /// </summary>
        public event EventHandler<EventArgs> StopTimerStopped;

        /// <summary>
        /// Event der gefeuert wird, wenn der Run-Timer gestoppt wurde.
        /// </summary>
        public event EventHandler<EventArgs> RunTimerStopped;

        #endregion // Events

        #region Methoden

        /// <summary>
        /// Started den asnchronen Sekunden-Timer für die Ausführungs-Dauer der Slot-Machine.
        /// </summary>
        /// <param name="runDurationSeconds">Anzahl Sekunden die während die SlotMachine laufen soll.</param>
        public void StartRunningSequence(int runDurationSeconds)
        {
            _runDurationSeconds = runDurationSeconds;
            _runSecondsCount = 0;

            BackgroundWorker runTimerTickWorker = new BackgroundWorker();
            runTimerTickWorker.DoWork += new DoWorkEventHandler(runTimerTickWorker_DoWork);
            runTimerTickWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(runTimerTickWorker_RunWorkerCompleted);
            runTimerTickWorker.RunWorkerAsync();
        }

        /// <summary>
        /// Started den asnchronen Sekunden-Timer für das Stoppen der einzelnen Slots.
        /// </summary>
        /// <param name="stopIntervalSeconds">Sekunden-Intervall für das Stoppen der Slots</param>
        public void StartStoppingSequence(int stopIntervalSeconds)
        {
            _stopIntervalSeconds = stopIntervalSeconds;
            _stopSecondsCount = 0;
            _stoppedSlotsCount = 0;

            BackgroundWorker stopTmerTickWorker = new BackgroundWorker();
            stopTmerTickWorker.DoWork += new DoWorkEventHandler(stopTimerTickWorker_DoWork);
            stopTmerTickWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(stopTimerTickWorker_RunWorkerCompleted);
            stopTmerTickWorker.RunWorkerAsync();
        }

        #endregion // Methoden

        #region Event-Handler

        /// <summary>
        /// Überprüft im Sekunden-Takt ob die Slot-Machine noch laufen darf.
        /// </summary>
        /// <param name="sender">Das auslösende Objekt.</param>
        /// <param name="eventArgs">DoWorkEventArgs.</param>
        private void runTimerTickWorker_DoWork(object sender, DoWorkEventArgs eventArgs)
        {
            while (!_stopRunningSequence)
            {
                if (_runSecondsCount >= _runDurationSeconds)
                {
                    _stopRunningSequence = true;
                }

                _runSecondsCount++;

                Thread.Sleep(1000);
            }
        }

        /// <summary>
        /// Wird ausgeführt wenn der Run-Timer durchlaufen ist und gestoppt werden soll.
        /// </summary>
        /// <param name="sender">Das auslösende Objekt.</param>
        /// <param name="eventArgs">RunWorkerCompletedEventArgs.</param>
        private void runTimerTickWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs eventArgs)
        {
            OnRunTimerStopped(new EventArgs());
        }

        /// <summary>
        /// Überprüft im Sekunden-Takt wann ein Slot gestoppt werden kann und Stopped den jeweiligen Slot wenn der richtige Zeipunkt erreicht.
        /// </summary>
        /// <param name="sender">Das auslösende Objekt.</param>
        /// <param name="eventArgs">DoWorkEventArgs.</param>
        private void stopTimerTickWorker_DoWork(object sender, DoWorkEventArgs eventArgs)
        {
            while (!_stopStoppingSequence)
            {
                if (_stoppedSlotsCount >= _numberOfSlots)
                {
                    _stopStoppingSequence = true;
                }
                else
                {
                    if (_stoppedSlotsCount == 0)
                    {
                        _stoppedSlotsCount++;

                        OnStopSlotRequestedRequested(new StopSlotRequestedEventArgs(_stoppedSlotsCount));
                    }
                    else if (_stopSecondsCount >= _stopIntervalSeconds)
                    {
                        _stoppedSlotsCount++;

                        OnStopSlotRequestedRequested(new StopSlotRequestedEventArgs(_stoppedSlotsCount));

                        _stopSecondsCount = 0;
                    }

                    _stopSecondsCount++;

                    Thread.Sleep(1000);
                }
            }
        }

        /// <summary>
        /// Wird ausgeführt wenn der Stop-Timer durchlaufen ist und gestoppt werden soll.
        /// </summary>
        /// <param name="sender">Das auslösende Objekt.</param>
        /// <param name="eventArgs">RunWorkerCompletedEventArgs.</param>
        private void stopTimerTickWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs eventArgs)
        {
            OnStopTimerStopped(new EventArgs());
        }

        /// <summary>
        /// Feuert den RunTimerStopped-Event.
        /// </summary>
        /// <param name="eventArgs">Standard EventArgs.</param>
        private void OnRunTimerStopped(EventArgs eventArgs)
        {
            EventHandler<EventArgs> handler = RunTimerStopped;

            if (handler != null)
            {
                handler(this, eventArgs);
            }
        }

        /// <summary>
        /// Feuert den StopSlotRequested-Event mit der Angabe, welcher Slot gestoppt werden soll.
        /// </summary>
        /// <param name="eventArgs">StopSlotRequestedEventArgs.</param>
        private void OnStopSlotRequestedRequested(StopSlotRequestedEventArgs eventArgs)
        {
            EventHandler<StopSlotRequestedEventArgs> handler = StopSlotRequested;

            if (handler != null)
            {
                handler(this, eventArgs);
            }
        }

        /// <summary>
        /// Feuert den StopTimerStopped-Event.
        /// </summary>
        /// <param name="eventArgs">Standard EventArgs.</param>
        private void OnStopTimerStopped(EventArgs eventArgs)
        {
            EventHandler<EventArgs> handler = StopTimerStopped;

            if (handler != null)
            {
                handler(this, eventArgs);
            }
        }

        #endregion // Event-Handler
    }
}
